package com.mobiporter.adias.tests;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import junit.framework.AssertionFailedError;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Assert;
import org.junit.Test;
import com.mobiporter.utils.DateUtils;
import com.mobiporter.adias.tags.model.MonthYear;

/**
 * > Test client for
 * 
 * 1. Getting the list of dates.
 * 2. Getting the list of month/year
 * 3. Checking validity of dates.
 * 4. Creating dates from string.
 * 5. Formatting dates to no-space-separated strings
 * 
 * @author Chetan
 *
 */
public class DateTest 
{
	public static final Log log = LogFactory.getLog(DateTest.class);
	private static final String DATE_PATTERN = "(\\d+)/(\\d+)/(\\d\\d\\d\\d)";
	private static final String OUTPUT_DATE_FORMAT = "ddMMyyyy";
	
	@Test
	public void testListOfDates()
	{
		Calendar cal = DateUtils.getCalendar();
		
		for (int i=1 ; i<31 ;i++)
		{
			cal.set(Calendar.DAY_OF_MONTH, i);
			Date d = cal.getTime() ;
			
			// the list should be like i,i+1.. 31,1,2,...i-1
			List<String> dates = DateUtils.getDatesFromThisDate(d);
			if (dates == null || dates.isEmpty() )
			{
				throw new AssertionFailedError();
			}
			Assert.assertEquals(31, dates.size());
			if (dates.size()!=31)
				throw new AssertionFailedError() ;
			int j = i ;
			for (String date : dates)
			{
				// If the day is before 31, then the progression should be 
				// i,i+1...31
				if (j < 31)
				{
					Assert.assertEquals(j+"", date);
					j++ ;
					continue ;
				}
				if (j == 31)
				{
					Assert.assertEquals(31+"", date);
					j = 1; // roll to the 1'st of the month.
					continue ;
				}
			}
		}
	}
	
	@Test
	public void testListOfMonthYear()
	{
		Calendar c = DateUtils.getCalendar() ;
		c.set(Calendar.DAY_OF_MONTH,20) ;
		c.set(Calendar.MONTH, Calendar.NOVEMBER);
		c.set(Calendar.YEAR, 2007);
		Date d = c.getTime() ;
		List<MonthYear> monthYears =  DateUtils.getMonthYearsFrom(d);
		
		if (monthYears == null || monthYears.isEmpty() || monthYears.size()!=6)
		{
			System.out.println("The month-years list is empty or null or is not of size 6");
			throw new AssertionFailedError() ;
		}
		
		String[] monthNames = {	DateUtils.months[10],
								DateUtils.months[11],
								DateUtils.months[0],
								DateUtils.months[1],
								DateUtils.months[2],
								DateUtils.months[3]};
		int[] months = {11,12,1,2,3,4};
		int[] years = {2007,2007,2008,2008,2008,2008};
		
		int i = 0 ;
		for (MonthYear monthYear : monthYears)
		{
			Assert.assertEquals(monthNames[i], monthYear.getMonthName());
			Assert.assertEquals(months[i], monthYear.getMonth());
			Assert.assertEquals(years[i], monthYear.getYear());
			i++ ;
		}
	}
	
	@Test(expected=IllegalArgumentException.class)
	public void testGetDateFromInvalidString()
	{
		String dateString = "31/11/2007";// There's no 31'st of November
		DateUtils.getDateFromString(dateString);	
	}
	
	@Test(expected=IllegalArgumentException.class)
	public void testGetDateFromNullString()
	{

		String dateString = null;
		DateUtils.getDateFromString(dateString);	
	}
	
	@Test(expected=IllegalArgumentException.class)
	public void testGetDateFromInvalidPattern()
	{
		String dateString = "12-3-2007";
		DateUtils.getDateFromString(dateString);
	}
	
	@Test
	public void testValidityOfDateWithBadDate()
	{
		String dateString = "31/11/2007";
		if (DateUtils.isValidDate(dateString, DATE_PATTERN))
		{
			throw new AssertionFailedError();
		}
	}
	
	@Test
	public void testValidityOfDateWithGoodDate()
	{
		String dateString = "30/11/2007";
		if (!DateUtils.isValidDate(dateString, DATE_PATTERN))
		{
			throw new AssertionFailedError() ;
		}
	}
	
	public void testGetDateWithCorrectDate()
	{
		String dateString = "30/11/2007";
		Date d = DateUtils.getDateFromString(dateString);
		if (d == null)
		{
			throw new AssertionFailedError() ;
		}
		Calendar cal = DateUtils.getCalendar() ;
		cal.setTime(d);
		
		// Test if the date is valid.
		if (cal.get(Calendar.YEAR) != 2007 || 
			cal.get(Calendar.MONTH) != 10 || 
			cal.get(Calendar.DAY_OF_MONTH) != 30)
		{
			throw new AssertionFailedError() ;
		}
	}
	
	
	@Test
	public void testDatePatterMatcherWithBadPattern()
	{
		String date = "21-23-2007";
		Assert.assertFalse(DateUtils.isProperDateFormat(date,DATE_PATTERN));

		date = "21/23/20xx";
		Assert.assertFalse(DateUtils.isProperDateFormat(date,DATE_PATTERN));

		date = "/23/20";
		Assert.assertFalse(DateUtils.isProperDateFormat(date,DATE_PATTERN));
		
	}
	
	@Test
	public void testDatePatterMatcherWithGoodPattern()
	{
		String date = "24/11/2007";
		if (!DateUtils.isProperDateFormat(date,DATE_PATTERN))
		{
			throw new AssertionFailedError() ;
		}
	}
	
	@Test
	public void testGetMonthFromDateString()
	{
		String dateString = "24/11/2007";
		int month = DateUtils.getMonthFromDateString(dateString,DATE_PATTERN);
		if (month!=11)
			throw new AssertionFailedError() ;
	}
	
	@Test
	public void testGetYearFromDateString()
	{
		String dateString = "24/11/2007";
		int month = DateUtils.getYearFromDateString(dateString,DATE_PATTERN);
		if (month!=2007)
			throw new AssertionFailedError() ;		
	}
	
	@Test
	public void testGetDateFromDateString()
	{
		String dateString = "24/11/2007";
		int day = DateUtils.getDayFromDateString(dateString,DATE_PATTERN);
		if (day!=24)
			throw new AssertionFailedError() ;	
	}
	
	@Test
	public void testFormatString()
	{
		Calendar c = DateUtils.getCalendar() ;
		c.set(Calendar.YEAR, 2007);
		c.set(Calendar.MONTH, 11);
		c.set(Calendar.DAY_OF_MONTH,30);
		String formattedDate = DateUtils.formatDate(c.getTime(),OUTPUT_DATE_FORMAT);
		Assert.assertEquals("30122007",formattedDate);
	}
	
	@Test
	public void testCalculateDifferenceInMonths()
	{
		Date today = getDateFromString("26/11/2007");
		
		Date testDate1 = getDateFromString("1/1/2008");
		Assert.assertEquals(2, DateUtils.getDifferenceInMonths(today, testDate1));
		
		Date testDate2 = getDateFromString("26/11/2006");
		Assert.assertEquals(-12, DateUtils.getDifferenceInMonths(today, testDate2));
		
		Date testDate3 = getDateFromString("1/12/2007");
		Assert.assertEquals(1, DateUtils.getDifferenceInMonths(today, testDate3));
		
		Date testDate4 = getDateFromString("31/12/2007");
		Assert.assertEquals(1, DateUtils.getDifferenceInMonths(today, testDate4));
	}
	
	@Test
	public void testGetDayFromDateString()
	{
		String testDate = "21/3/2007";
		Assert.assertEquals("21", DateUtils.getDayFromDate(testDate));
		testDate = "3/11/2007";
		Assert.assertEquals("3", DateUtils.getDayFromDate(testDate));
	}

	@Test
	public void testGetMonFromDateString()
	{
		String testDate = "21/3/2007";
		Assert.assertEquals("3/2007", DateUtils.getMonFromDate(testDate));
		testDate = "3/11/2007";
		Assert.assertEquals("11/2007", DateUtils.getMonFromDate(testDate));
	}
	
	private Date getDateFromString(String date)
	{
		return DateUtils.getDateFromString(date);
	}
	
}
